#include "UDPManager.h"
#include <esp_log.h>

static constexpr const char *TAG = "UDPManager";
#define DEBUG 0

namespace app
{
    void udpPort::start()
    {
        sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
        if (sock < 0)
        {
            ESP_LOGE(TAG, "Failed to create socket");
            return;
        }

        // 1. 绑定到4210端口（这样发送也会从4210端口出去）
        struct sockaddr_in my_addr;
        my_addr.sin_family = AF_INET;
        my_addr.sin_port = htons(local_port); // 🎯 固定使用4210端口
        my_addr.sin_addr.s_addr = htonl(INADDR_ANY);

        if (bind(sock, (struct sockaddr *)&my_addr, sizeof(my_addr)) < 0)
        {
            ESP_LOGE(TAG, "无法绑定端口%d", local_port);
            close(sock);
            return;
        }

#if DEBUG
        ESP_LOGI(TAG, "✅ 成功绑定端口%d", local_port);
#endif

        // 2. 启用广播功能
        int broadcast_enable = 1;
        setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &broadcast_enable, sizeof(broadcast_enable));

        // 3. 配置广播目标（12345端口）
        broadcast_addr.sin_family = AF_INET;
        broadcast_addr.sin_port = htons(broadcast_port); // 发送到12345端口
        broadcast_addr.sin_addr.s_addr = inet_addr("255.255.255.255");

        xTaskCreate(
            [](void *a)
            {
                auto self = static_cast<udpPort *>(a);
                for (;;)
                {
                    // 📥 非阻塞接收（在4210端口接收）
                    struct timeval tv = {.tv_sec = 1, .tv_usec = 0};
                    fd_set readfds;
                    FD_ZERO(&readfds);
                    FD_SET(self->sock, &readfds);

                    if (select(self->sock + 1, &readfds, NULL, NULL, &tv) > 0)
                    {
                        if (FD_ISSET(self->sock, &readfds))
                        {
                            char recv_buffer[1024];
                            struct sockaddr_in client_addr;
                            socklen_t client_len = sizeof(client_addr);

                            int recv_len = recvfrom(self->sock, recv_buffer, sizeof(recv_buffer) - 1, 0,
                                                    (struct sockaddr *)&client_addr, &client_len);

                            if (recv_len > 0)
                            {
                                recv_buffer[recv_len] = 0;
#if DEBUG
                                ESP_LOGI(TAG, "📥 在4210端口收到来自 %s:%d 的消息: %s",
                                         inet_ntoa(client_addr.sin_addr),
                                         ntohs(client_addr.sin_port),
                                         recv_buffer);
#endif

                                if (self->on_receive)
                                {
                                    self->on_receive(recv_buffer, recv_len);
                                }
                            }
                        }
                    }
                }
                vTaskDelete(nullptr);
            },
            "udp recv task",
            4096,
            this,
            10,
            nullptr);
    }

    int udpPort::send(const char *data, size_t len)
    {
        return sendto(sock, data, len, 0, (struct sockaddr *)&broadcast_addr, sizeof(broadcast_addr));
    }

    int udpPort::send(const std::string &str)
    {
        return sendto(sock, str.c_str(), str.size(), 0,
                      (struct sockaddr *)&broadcast_addr, sizeof(broadcast_addr));
    }
}